<?php

define('FPDF_FONTPATH','/webs/vlfntime/library/VLFN/font/');
define('DEFAULT_WIDTH', 7.5);

//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

class VLFN_Pdf extends VLFN_Fpdf
{

//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	
	function Table($data, $aHeader, $aWidth, $aUser = false)
	{
		if(0 >= sizeof($data))
		{
			return false;
		}  
		
	   //Header

	   $this->SetDrawColor(1, 1, 1);
	   $this->SetLineWidth(.3);
	   $this->SetFont('', 'B');
       $this->SetTextColor(0);	   
	   
	   $this->SetX(0);    
	   $this->SetY(25);
	   
	   if($aUser)
	   {
		   foreach ($aUser as $k => $v)
	       {
	            $this->SetFillColor(230, 242, 217);
	            $this->Cell(40, ceil(FONT_SIZE /2) + 1, $k . ': ' . $v, 0, 0, 'C', 1);
	       }  
	       $this->Ln();
	       $this->Ln();
	   }
	   $tw = 0;
	   
	   foreach ($aHeader as $header)
       {
		   for($i = 0; $i <= sizeof($header['data']); $i++)
		   {
		   	   $width = isset($aWidth[$i]) ? $aWidth[$i] : DEFAULT_WIDTH;
		   	   $label = isset($header['data'][$i]) ? $header['data'][$i] : '';
		   	   $color = isset($header['color'][$i]) ? $header['color'][$i] : '-';
		       $tw += $width;

		       if ('pink' == $color)
		       {
		       	     $this->SetFillColor(136, 185, 64);
		       }
		       else
		       {
		       	     $this->SetFillColor(230, 242, 217);
		       }
		       $this->Cell($width, ceil(FONT_SIZE /2) + 1, $label, 1, 0, 'C', 1);
		   }
		   $this->Ln();
       }   
       $this->SetFillColor(240, 239, 239);
	 
	   $fill   = false;
	   foreach ($data as $oData)
	   {
	   	for($i = 0; $i < sizeof($oData['data']); $i++)
           {
               $color = isset($oData['color'][$i]) ? $oData['color'][$i] : '-';

               if($fill)
               {
                     $this->SetFillColor(240, 239, 239);
               }
               else
               {
                     $this->SetFillColor(255, 255, 255);
               }
               
               if ('pink' == $color)
               {
                     $this->SetFillColor(136, 185, 64);
               }
           	
           	    $this->Cell(isset($aWidth[$i]) ? $aWidth[$i] : DEFAULT_WIDTH, 
           	                ceil(FONT_SIZE /2), 
           	                isset($oData['data'][$i]) ? $oData['data'][$i] : '', 
           	                1, 0, 'C', 1);
           }
	   	
	       $this->Ln();
	       $fill   =! $fill;
	   }
	    $this->Ln();
    }
    
//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    function Footer() 
    {
	    $this->SetY(-15);
	    $this->SetFont('Times','',8);
	    $this->Cell(0,10,'Page  '.$this->PageNo().'/{nb}',0,0,'C');
    }
     
//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    
    function Header()
	{
		$oID = 1;
		$date = strftime('%A, %d %B %Y');
		//Logo
		$this->Image($_SERVER["DOCUMENT_ROOT"] . '/i/logo.png', 30, 5, 100);
		
		$this->Ln(10);
		
		// Invoice Number and date
//		$this->SetFont('Arial','B',10);
//		$this->SetTextColor(0,102,153);
//		$this->SetY(37);
//		$this->MultiCell(50,4,"Invoice: #" . $oID . "n" . $date ,0,'L');
		
		// Company Address
//		$this->SetX(0);
//		$this->SetY(10);
//		$this->SetFont('Arial','B',10);
//		$this->SetTextColor(0,102,153);
//		$this->Ln(0);
//		$this->Cell(149);
//		$this->MultiCell(50, 3.5, 'ololo', 0,'R');
	} 

//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	
     function ColoredTable($header,$data) 
     {
        // Colors, line width and bold font
        $this->SetFillColor(255, 0, 0);
        $this->SetTextColor(255);
        $this->SetDrawColor(128, 0, 0);
        $this->SetLineWidth(0.3);
        $this->SetFont('', 'B');
        // Header
        $w = array(40, 35, 40, 45);
        $num_headers = count($header);
        for($i = 0; $i < $num_headers; ++$i) 
        {
            $this->Cell($w[$i], 7, $header[$i], 1, 0, 'C', 1);
        }
        $this->Ln();
        // Color and font restoration
        $this->SetFillColor(224, 235, 255);
        $this->SetTextColor(0);
        $this->SetFont('');
        // Data
        $fill = 0;
        foreach($data as $row) 
        {
            $this->Cell($w[0], 6, $row[0], 'LR', 0, 'L', $fill);
            $this->Cell($w[1], 6, $row[1], 'LR', 0, 'L', $fill);
            $this->Cell($w[2], 6, number_format($row[2]), 'LR', 0, 'R', $fill);
            $this->Cell($w[3], 6, number_format($row[3]), 'LR', 0, 'R', $fill);
            $this->Ln();
            $fill=!$fill;
        }
        $this->Cell(array_sum($w), 0, '', 'T');
    }
    
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    
	
	function RoundedRect($x, $y, $w, $h,$r, $style = '')
	{
		$k     = $this->k;
		$hp    = $this->h;
		if($style == 'F')
		{
		  $op  = 'f';
		}
		elseif($style == 'FD' or $styl == 'DF')
		{
		  $op  = 'B';
		}
		else
		{
		  $op  = 'S';
		}
		$MyArc = 4/3 * (sqrt(2) - 1);
		$this->_out(sprintf('%.2f %.2f m',($x+$r)*$k,($hp-$y)*$k ));
		$xc    = $x+$w-$r ;
		$yc    = $y+$r;
		$this->_out(sprintf('%.2f %.2f l', $xc*$k,($hp-$y)*$k ));
		
		$this->_Arc($xc + $r*$MyArc, $yc - $r, $xc + $r, $yc - $r*$MyArc, $xc + $r, $yc);
		$xc    = $x+$w-$r ;
		$yc    = $y+$h-$r;
		$this->_out(sprintf('%.2f %.2f l',($x+$w)*$k,($hp-$yc)*$k));
		$this->_Arc($xc + $r, $yc + $r*$MyArc, $xc + $r*$MyArc, $yc + $r, $xc, $yc + $r);
		$xc    = $x+$r ;
		$yc    = $y+$h-$r;
		$this->_out(sprintf('%.2f %.2f l',$xc*$k,($hp-($y+$h))*$k));
		$this->_Arc($xc - $r*$MyArc, $yc + $r, $xc - $r, $yc + $r*$MyArc, $xc - $r, $yc);
		$xc    = $x+$r ;
		$yc    = $y+$r;
		$this->_out(sprintf('%.2f %.2f l',($x)*$k,($hp-$yc)*$k ));
		$this->_Arc($xc - $r, $yc - $r*$MyArc, $xc - $r*$MyArc, $yc - $r, $xc, $yc - $r);
		$this->_out($op);
	}

//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

	function _Arc($x1, $y1, $x2, $y2, $x3, $y3)
	{
		$h = $this->h;
		$this->_out(sprintf('%.2f %.2f %.2f %.2f %.2f %.2f c ', $x1*$this->k, ($h-$y1)*$this->k,
		$x2*$this->k, ($h-$y2)*$this->k, $x3*$this->k, ($h-$y3)*$this->k));
	} 
	
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	
	public function writeHTML($html, $ln=true, $fill=false, $reseth=false, $cell=false, $align='') {
            $gvars = $this->getGraphicVars();
            // store current values
            $prevPage = $this->page;
            $prevlMargin = $this->lMargin;
            $prevrMargin = $this->rMargin;
            $curfontname = $this->FontFamily;
            $curfontstyle = $this->FontStyle;
            $curfontsize = $this->FontSizePt;
            $curfontascent = $this->getFontAscent($curfontname, $curfontstyle, $curfontsize);
            $curfontdescent = $this->getFontDescent($curfontname, $curfontstyle, $curfontsize);
            $this->newline = true;
            $newline = true;
            $startlinepage = $this->page;
            $minstartliney = $this->y;
            $maxbottomliney = 0;
            $startlinex = $this->x;
            $startliney = $this->y;
            $yshift = 0;
            $loop = 0;
            $curpos = 0;
            $this_method_vars = array();
            $undo = false;
            $fontaligned = false;
            $this->premode = false;
            if (isset($this->PageAnnots[$this->page])) {
                $pask = count($this->PageAnnots[$this->page]);
            } else {
                $pask = 0;
            }
            if (!$this->InFooter) {
                if (isset($this->footerlen[$this->page])) {
                    $this->footerpos[$this->page] = $this->pagelen[$this->page] - $this->footerlen[$this->page];
                } else {
                    $this->footerpos[$this->page] = $this->pagelen[$this->page];
                }
                $startlinepos = $this->footerpos[$this->page];
            } else {
                $startlinepos = $this->pagelen[$this->page];
            }
            $lalign = $align;
            $plalign = $align;
            if ($this->rtl) {
                $w = $this->x - $this->lMargin;
            } else {
                $w = $this->w - $this->rMargin - $this->x;
            }
            $w -= (2 * $this->cMargin);
            if ($cell) {
                if ($this->rtl) {
                    $this->x -= $this->cMargin;
                    $this->lMargin += $this->cMargin;
                } else {
                    $this->x += $this->cMargin;
                    $this->rMargin += $this->cMargin;
                }
            }
            if ($this->customlistindent >= 0) {
                $this->listindent = $this->customlistindent;
            } else {
                $this->listindent = $this->GetStringWidth('0000');
            }
            $this->listindentlevel = 0;
            // save previous states
            $prev_cell_height_ratio = $this->cell_height_ratio;
            $prev_listnum = $this->listnum;
            $prev_listordered = $this->listordered;
            $prev_listcount = $this->listcount;
            $prev_lispacer = $this->lispacer;
            $this->listnum = 0;
            $this->listordered = array();
            $this->listcount = array();
            $this->lispacer = '';
            if (($this->empty_string($this->lasth)) OR ($reseth)) {
                //set row height
                $this->lasth = $this->FontSize * $this->cell_height_ratio;
            }
            $dom = $this->getHtmlDomArray($html);
            $maxel = count($dom);
            $key = 0;
            while ($key < $maxel) {
                if ($dom[$key]['tag'] AND isset($dom[$key]['attribute']['pagebreak'])) {
                    // check for pagebreak
                    if (($dom[$key]['attribute']['pagebreak'] == 'true') OR ($dom[$key]['attribute']['pagebreak'] == 'left') OR ($dom[$key]['attribute']['pagebreak'] == 'right')) {
                        // add a page (or trig AcceptPageBreak() for multicolumn mode)
                        $this->checkPageBreak($this->PageBreakTrigger + 1);
                    }
                    if ((($dom[$key]['attribute']['pagebreak'] == 'left') AND (((!$this->rtl) AND (($this->page % 2) == 0)) OR (($this->rtl) AND (($this->page % 2) != 0))))
                        OR (($dom[$key]['attribute']['pagebreak'] == 'right') AND (((!$this->rtl) AND (($this->page % 2) != 0)) OR (($this->rtl) AND (($this->page % 2) == 0))))) {
                        // add a page (or trig AcceptPageBreak() for multicolumn mode)
                        $this->checkPageBreak($this->PageBreakTrigger + 1);
                    }
                }
                if ($dom[$key]['tag'] AND $dom[$key]['opening'] AND isset($dom[$key]['attribute']['nobr']) AND ($dom[$key]['attribute']['nobr'] == 'true')) {
                    if (isset($dom[($dom[$key]['parent'])]['attribute']['nobr']) AND ($dom[($dom[$key]['parent'])]['attribute']['nobr'] == 'true')) {
                        $dom[$key]['attribute']['nobr'] = false;
                    } else {
                        // store current object
                        $this->startTransaction();
                        // save this method vars
                        $this_method_vars['html'] = $html;
                        $this_method_vars['ln'] = $ln;
                        $this_method_vars['fill'] = $fill;
                        $this_method_vars['reseth'] = $reseth;
                        $this_method_vars['cell'] = $cell;
                        $this_method_vars['align'] = $align;
                        $this_method_vars['gvars'] = $gvars;
                        $this_method_vars['prevPage'] = $prevPage;
                        $this_method_vars['prevlMargin'] = $prevlMargin;
                        $this_method_vars['prevrMargin'] = $prevrMargin;
                        $this_method_vars['curfontname'] = $curfontname;
                        $this_method_vars['curfontstyle'] = $curfontstyle;
                        $this_method_vars['curfontsize'] = $curfontsize;
                        $this_method_vars['curfontascent'] = $curfontascent;
                        $this_method_vars['curfontdescent'] = $curfontdescent;
                        $this_method_vars['minstartliney'] = $minstartliney;
                        $this_method_vars['maxbottomliney'] = $maxbottomliney;
                        $this_method_vars['yshift'] = $yshift;
                        $this_method_vars['startlinepage'] = $startlinepage;
                        $this_method_vars['startlinepos'] = $startlinepos;
                        $this_method_vars['startlinex'] = $startlinex;
                        $this_method_vars['startliney'] = $startliney;
                        $this_method_vars['newline'] = $newline;
                        $this_method_vars['loop'] = $loop;
                        $this_method_vars['curpos'] = $curpos;
                        $this_method_vars['pask'] = $pask;
                        $this_method_vars['lalign'] = $lalign;
                        $this_method_vars['plalign'] = $plalign;
                        $this_method_vars['w'] = $w;
                        $this_method_vars['prev_cell_height_ratio'] = $prev_cell_height_ratio;
                        $this_method_vars['prev_listnum'] = $prev_listnum;
                        $this_method_vars['prev_listordered'] = $prev_listordered;
                        $this_method_vars['prev_listcount'] = $prev_listcount;
                        $this_method_vars['prev_lispacer'] = $prev_lispacer;
                        $this_method_vars['fontaligned'] = $fontaligned;
                        $this_method_vars['key'] = $key;
                        $this_method_vars['dom'] = $dom;
                    }
                }
                // print THEAD block
                if (($dom[$key]['value'] == 'tr') AND isset($dom[$key]['thead']) AND $dom[$key]['thead']) {
                    if (isset($dom[$key]['parent']) AND isset($dom[$dom[$key]['parent']]['thead']) AND !$this->empty_string($dom[$dom[$key]['parent']]['thead'])) {
                        $this->inthead = true;
                        // print table header (thead)
                        $this->writeHTML($this->thead, false, false, false, false, '');
                        if (($this->start_transaction_page == ($this->numpages - 1)) OR ($this->y < $this->start_transaction_y) OR ($this->checkPageBreak($this->lasth, '', false))) {
                            // restore previous object
                            $this->rollbackTransaction(true);
                            // restore previous values
                            foreach ($this_method_vars as $vkey => $vval) {
                                $$vkey = $vval;
                            }
                            // disable table header
                            $tmp_thead = $this->thead;
                            $this->thead = '';
                            // add a page (or trig AcceptPageBreak() for multicolumn mode)
                            $pre_y = $this->y;
                            if ((!$this->checkPageBreak($this->PageBreakTrigger + 1)) AND ($this->y < $pre_y)) {
                                // fix for multicolumn mode
                                $startliney = $this->y;
                            }
                            $this->start_transaction_page = $this->page;
                            $this->start_transaction_y = $this->y;
                            // restore table header
                            $this->thead = $tmp_thead;
                            // fix table border properties
                            if (isset($dom[$dom[$key]['parent']]['attribute']['cellspacing'])) {
                                $tmp_cellspacing = $this->getHTMLUnitToUnits($dom[$dom[$key]['parent']]['attribute']['cellspacing'], 1, 'px');
                            } else {
                                $tmp_cellspacing = 0;
                            }
                            $dom[$dom[$key]['parent']]['borderposition']['page'] = $this->page;
                            $dom[$dom[$key]['parent']]['borderposition']['column'] = $this->current_column;
                            $dom[$dom[$key]['parent']]['borderposition']['y'] = $this->y + $tmp_cellspacing;
                            $xoffset = ($this->x - $dom[$dom[$key]['parent']]['borderposition']['x']);
                            $dom[$dom[$key]['parent']]['borderposition']['x'] += $xoffset;
                            $dom[$dom[$key]['parent']]['borderposition']['xmax'] += $xoffset;
                            // print table header (thead)
                            $this->writeHTML($this->thead, false, false, false, false, '');
                        }
                    }
                    // move $key index forward to skip THEAD block
                    while ( ($key < $maxel) AND (!(
                        ($dom[$key]['tag'] AND $dom[$key]['opening'] AND ($dom[$key]['value'] == 'tr') AND (!isset($dom[$key]['thead']) OR !$dom[$key]['thead']))
                        OR ($dom[$key]['tag'] AND (!$dom[$key]['opening']) AND ($dom[$key]['value'] == 'table'))) )) {
                        ++$key;
                    }
                }
                if ($dom[$key]['tag'] OR ($key == 0)) {
                    if ((($dom[$key]['value'] == 'table') OR ($dom[$key]['value'] == 'tr')) AND (isset($dom[$key]['align']))) {
                        $dom[$key]['align'] = ($this->rtl) ? 'R' : 'L';
                    }
                    // vertically align image in line
                    if ((!$this->newline) AND ($dom[$key]['value'] == 'img') AND (isset($dom[$key]['height'])) AND ($dom[$key]['height'] > 0)) {
                        // get image height
                        $imgh = $this->getHTMLUnitToUnits($dom[$key]['height'], $this->lasth, 'px');
                        // check for automatic line break
                        $autolinebreak = false;
                        if (isset($dom[$key]['width']) AND ($dom[$key]['width'] > 0)) {
                            $imgw = $this->getHTMLUnitToUnits($dom[$key]['width'], 1, 'px', false);
                            if (($this->rtl AND (($this->x - $imgw) < ($this->lMargin + $this->cMargin)))
                                OR (!$this->rtl AND (($this->x + $imgw) > ($this->w - $this->rMargin - $this->cMargin)))) {
                                // add automatic line break
                                $autolinebreak = true;
                                $this->Ln('', $cell);
                                // go back to evaluate this line break
                                --$key;
                            }
                        }
                        if (!$autolinebreak) {
                            if (!$this->InFooter) {
                                $pre_y = $this->y;
                                // check for page break
                                if ((!$this->checkPageBreak($imgh)) AND ($this->y < $pre_y)) {
                                    // fix for multicolumn mode
                                    $startliney = $this->y;
                                }
                            }
                            if ($this->page > $startlinepage) {
                                // fix line splitted over two pages
                                if (isset($this->footerlen[$startlinepage])) {
                                    $curpos = $this->pagelen[$startlinepage] - $this->footerlen[$startlinepage];
                                }
                                // line to be moved one page forward
                                $pagebuff = $this->getPageBuffer($startlinepage);
                                $linebeg = substr($pagebuff, $startlinepos, ($curpos - $startlinepos));
                                $tstart = substr($pagebuff, 0, $startlinepos);
                                $tend = substr($this->getPageBuffer($startlinepage), $curpos);
                                // remove line from previous page
                                $this->setPageBuffer($startlinepage, $tstart.''.$tend);
                                $pagebuff = $this->getPageBuffer($this->page);
                                $tstart = substr($pagebuff, 0, $this->cntmrk[$this->page]);
                                $tend = substr($pagebuff, $this->cntmrk[$this->page]);
                                // add line start to current page
                                $yshift = $minstartliney - $this->y;
                                if ($fontaligned) {
                                    $yshift += ($curfontsize / $this->k);
                                }
                                $try = sprintf('1 0 0 1 0 %.3F cm', ($yshift * $this->k));
                                $this->setPageBuffer($this->page, $tstart."\nq\n".$try."\n".$linebeg."\nQ\n".$tend);
                                // shift the annotations and links
                                if (isset($this->PageAnnots[$this->page])) {
                                    $next_pask = count($this->PageAnnots[$this->page]);
                                } else {
                                    $next_pask = 0;
                                }
                                if (isset($this->PageAnnots[$startlinepage])) {
                                    foreach ($this->PageAnnots[$startlinepage] as $pak => $pac) {
                                        if ($pak >= $pask) {
                                            $this->PageAnnots[$this->page][] = $pac;
                                            unset($this->PageAnnots[$startlinepage][$pak]);
                                            $npak = count($this->PageAnnots[$this->page]) - 1;
                                            $this->PageAnnots[$this->page][$npak]['y'] -= $yshift;
                                        }
                                    }
                                }
                                $pask = $next_pask;
                                $startlinepos = $this->cntmrk[$this->page];
                                $startlinepage = $this->page;
                                $startliney = $this->y;
                                $this->newline = false;
                            }
                            $this->y += ((($curfontsize * $this->cell_height_ratio / $this->k) + $curfontascent - $curfontdescent) / 2) - $imgh;
                            $minstartliney = min($this->y, $minstartliney);
                            $maxbottomliney = ($startliney + ($this->FontSize * $this->cell_height_ratio));
                        }
                    } elseif (isset($dom[$key]['fontname']) OR isset($dom[$key]['fontstyle']) OR isset($dom[$key]['fontsize']) OR isset($dom[$key]['line-height'])) {
                        // account for different font size
                        $pfontname = $curfontname;
                        $pfontstyle = $curfontstyle;
                        $pfontsize = $curfontsize;
                        $fontname = isset($dom[$key]['fontname']) ? $dom[$key]['fontname'] : $curfontname;
                        $fontstyle = isset($dom[$key]['fontstyle']) ? $dom[$key]['fontstyle'] : $curfontstyle;
                        $fontsize = isset($dom[$key]['fontsize']) ? $dom[$key]['fontsize'] : $curfontsize;
                        $fontascent = $this->getFontAscent($fontname, $fontstyle, $fontsize);
                        $fontdescent = $this->getFontDescent($fontname, $fontstyle, $fontsize);
                        if (($fontname != $curfontname) OR ($fontstyle != $curfontstyle) OR ($fontsize != $curfontsize) OR ($this->cell_height_ratio != $dom[$key]['line-height'])) {
                            if ((!$this->newline) AND ($key < ($maxel - 1))
                                AND ((is_numeric($fontsize) AND ($fontsize >= 0) AND is_numeric($curfontsize) AND ($curfontsize >= 0) AND ($fontsize != $curfontsize))
                                    OR ($this->cell_height_ratio != $dom[$key]['line-height']))) {
                                if ($this->page > $startlinepage) {
                                    // fix lines splitted over two pages
                                    if (isset($this->footerlen[$startlinepage])) {
                                        $curpos = $this->pagelen[$startlinepage] - $this->footerlen[$startlinepage];
                                    }
                                    // line to be moved one page forward
                                    $pagebuff = $this->getPageBuffer($startlinepage);
                                    $linebeg = substr($pagebuff, $startlinepos, ($curpos - $startlinepos));
                                    $tstart = substr($pagebuff, 0, $startlinepos);
                                    $tend = substr($this->getPageBuffer($startlinepage), $curpos);
                                    // remove line start from previous page
                                    $this->setPageBuffer($startlinepage, $tstart.''.$tend);
                                    $pagebuff = $this->getPageBuffer($this->page);
                                    $tstart = substr($pagebuff, 0, $this->cntmrk[$this->page]);
                                    $tend = substr($pagebuff, $this->cntmrk[$this->page]);
                                    // add line start to current page
                                    $yshift = $minstartliney - $this->y;
                                    $try = sprintf('1 0 0 1 0 %.3F cm', ($yshift * $this->k));
                                    $this->setPageBuffer($this->page, $tstart."\nq\n".$try."\n".$linebeg."\nQ\n".$tend);
                                    // shift the annotations and links
                                    if (isset($this->PageAnnots[$this->page])) {
                                        $next_pask = count($this->PageAnnots[$this->page]);
                                    } else {
                                        $next_pask = 0;
                                    }
                                    if (isset($this->PageAnnots[$startlinepage])) {
                                        foreach ($this->PageAnnots[$startlinepage] as $pak => $pac) {
                                            if ($pak >= $pask) {
                                                $this->PageAnnots[$this->page][] = $pac;
                                                unset($this->PageAnnots[$startlinepage][$pak]);
                                                $npak = count($this->PageAnnots[$this->page]) - 1;
                                                $this->PageAnnots[$this->page][$npak]['y'] -= $yshift;
                                            }
                                        }
                                    }
                                    $pask = $next_pask;
                                    $startlinepos = $this->cntmrk[$this->page];
                                    $startlinepage = $this->page;
                                    $startliney = $this->y;
                                }
                                if (!isset($dom[$key]['line-height'])) {
                                    $dom[$key]['line-height'] = $this->cell_height_ratio;
                                }
                                if (!$dom[$key]['block']) {
                                    $this->y += (((($curfontsize * $this->cell_height_ratio ) - ($fontsize * $dom[$key]['line-height'])) / $this->k) + $curfontascent - $fontascent - $curfontdescent + $fontdescent) / 2;
                                    if (($dom[$key]['value'] != 'sup') AND ($dom[$key]['value'] != 'sub')) {
                                        $minstartliney = min($this->y, $minstartliney);
                                        $maxbottomliney = max(($this->y + (($fontsize * $this->cell_height_ratio) / $this->k)), $maxbottomliney);
                                    }
                                }
                                $this->cell_height_ratio = $dom[$key]['line-height'];
                                $fontaligned = true;
                            }
                            $this->SetFont($fontname, $fontstyle, $fontsize);
                            $this->lasth = $this->FontSize * $this->cell_height_ratio;
                            $curfontname = $fontname;
                            $curfontstyle = $fontstyle;
                            $curfontsize = $fontsize;
                            $curfontascent = $fontascent;
                            $curfontdescent = $fontdescent;
                        }
                    }
                    // set text rendering mode
                    $textstroke = isset($dom[$key]['stroke']) ? $dom[$key]['stroke'] : $this->textstrokewidth;
                    $textfill = isset($dom[$key]['fill']) ? $dom[$key]['fill'] : (($this->textrendermode % 2) == 0);
                    $textclip = isset($dom[$key]['clip']) ? $dom[$key]['clip'] : ($this->textrendermode > 3);
                    $this->setTextRenderingMode($textstroke, $textfill, $textclip);
                    if (($plalign == 'J') AND $dom[$key]['block']) {
                        $plalign = '';
                    }
                    // get current position on page buffer
                    $curpos = $this->pagelen[$startlinepage];
                    if (isset($dom[$key]['bgcolor']) AND ($dom[$key]['bgcolor'] !== false)) {
                        $this->SetFillColorArray($dom[$key]['bgcolor']);
                        $wfill = true;
                    } else {
                        $wfill = $fill | false;
                    }
                    if (isset($dom[$key]['fgcolor']) AND ($dom[$key]['fgcolor'] !== false)) {
                        $this->SetTextColorArray($dom[$key]['fgcolor']);
                    }
                    if (isset($dom[$key]['strokecolor']) AND ($dom[$key]['strokecolor'] !== false)) {
                        $this->SetDrawColorArray($dom[$key]['strokecolor']);
                    }
                    if (isset($dom[$key]['align'])) {
                        $lalign = $dom[$key]['align'];
                    }
                    if ($this->empty_string($lalign)) {
                        $lalign = $align;
                    }
                }
                // align lines
                if ($this->newline AND (strlen($dom[$key]['value']) > 0) AND ($dom[$key]['value'] != 'td') AND ($dom[$key]['value'] != 'th')) {
                    $newline = true;
                    $fontaligned = false;
                    // we are at the beginning of a new line
                    if (isset($startlinex)) {
                        $yshift = $minstartliney - $startliney;
                        if (($yshift > 0) OR ($this->page > $startlinepage)) {
                            $yshift = 0;
                        }
                        $t_x = 0;
                        // the last line must be shifted to be aligned as requested
                        $linew = abs($this->endlinex - $startlinex);
                        $pstart = substr($this->getPageBuffer($startlinepage), 0, $startlinepos);
                        if (isset($opentagpos) AND isset($this->footerlen[$startlinepage]) AND (!$this->InFooter)) {
                            $this->footerpos[$startlinepage] = $this->pagelen[$startlinepage] - $this->footerlen[$startlinepage];
                            $midpos = min($opentagpos, $this->footerpos[$startlinepage]);
                        } elseif (isset($opentagpos)) {
                            $midpos = $opentagpos;
                        } elseif (isset($this->footerlen[$startlinepage]) AND (!$this->InFooter)) {
                            $this->footerpos[$startlinepage] = $this->pagelen[$startlinepage] - $this->footerlen[$startlinepage];
                            $midpos = $this->footerpos[$startlinepage];
                        } else {
                            $midpos = 0;
                        }
                        if ($midpos > 0) {
                            $pmid = substr($this->getPageBuffer($startlinepage), $startlinepos, ($midpos - $startlinepos));
                            $pend = substr($this->getPageBuffer($startlinepage), $midpos);
                        } else {
                            $pmid = substr($this->getPageBuffer($startlinepage), $startlinepos);
                            $pend = '';
                        }
                        if ((isset($plalign) AND ((($plalign == 'C') OR ($plalign == 'J') OR (($plalign == 'R') AND (!$this->rtl)) OR (($plalign == 'L') AND ($this->rtl)))))) {
                            // calculate shifting amount
                            $tw = $w;
                            if (($plalign == 'J') AND $this->isRTLTextDir() AND ($this->num_columns > 1)) {
                                $tw += $this->cMargin;
                            }
                            if ($this->lMargin != $prevlMargin) {
                                $tw += ($prevlMargin - $this->lMargin);
                            }
                            if ($this->rMargin != $prevrMargin) {
                                $tw += ($prevrMargin - $this->rMargin);
                            }
                            $one_space_width = $this->GetStringWidth(chr(32));
                            $no = 0; // number of spaces on a line contained on a single block
                            if ($this->isRTLTextDir()) { // RTL
                                // remove left space if exist
                                $pos1 = $this->revstrpos($pmid, '[(');
                                if ($pos1 > 0) {
                                    $pos1 = intval($pos1);
                                    if ($this->isUnicodeFont()) {
                                        $pos2 = intval($this->revstrpos($pmid, '[('.chr(0).chr(32)));
                                        $spacelen = 2;
                                    } else {
                                        $pos2 = intval($this->revstrpos($pmid, '[('.chr(32)));
                                        $spacelen = 1;
                                    }
                                    if ($pos1 == $pos2) {
                                        $pmid = substr($pmid, 0, ($pos1 + 2)).substr($pmid, ($pos1 + 2 + $spacelen));
                                        if (substr($pmid, $pos1, 4) == '[()]') {
                                            $linew -= $one_space_width;
                                        } elseif ($pos1 == strpos($pmid, '[(')) {
                                            $no = 1;
                                        }
                                    }
                                }
                            } else { // LTR
                                // remove right space if exist
                                $pos1 = $this->revstrpos($pmid, ')]');
                                if ($pos1 > 0) {
                                    $pos1 = intval($pos1);
                                    if ($this->isUnicodeFont()) {
                                        $pos2 = intval($this->revstrpos($pmid, chr(0).chr(32).')]')) + 2;
                                        $spacelen = 2;
                                    } else {
                                        $pos2 = intval($this->revstrpos($pmid, chr(32).')]')) + 1;
                                        $spacelen = 1;
                                    }
                                    if ($pos1 == $pos2) {
                                        $pmid = substr($pmid, 0, ($pos1 - $spacelen)).substr($pmid, $pos1);
                                        $linew -= $one_space_width;
                                    }
                                }
                            }
                            $mdiff = ($tw - $linew);
                            if ($plalign == 'C') {
                                if ($this->rtl) {
                                    $t_x = -($mdiff / 2);
                                } else {
                                    $t_x = ($mdiff / 2);
                                }
                            } elseif ($plalign == 'R') {
                                // right alignment on LTR document
                                $t_x = $mdiff;
                            } elseif ($plalign == 'L') {
                                // left alignment on RTL document
                                $t_x = -$mdiff;
                            } elseif (($plalign == 'J') AND ($plalign == $lalign)) {
                                // Justification
                                if ($this->isRTLTextDir()) {
                                    // align text on the left
                                    $t_x = -$mdiff;
                                }
                                $ns = 0; // number of spaces
                                $pmidtemp = $pmid;
                                // escape special characters
                                $pmidtemp = preg_replace('/[\\\][\(]/x', '\\#!#OP#!#', $pmidtemp);
                                $pmidtemp = preg_replace('/[\\\][\)]/x', '\\#!#CP#!#', $pmidtemp);
                                // search spaces
                                if (preg_match_all('/\[\(([^\)]*)\)\]/x', $pmidtemp, $lnstring, PREG_PATTERN_ORDER)) {
                                    $spacestr = $this->getSpaceString();
                                    $maxkk = count($lnstring[1]) - 1;
                                    for ($kk=0; $kk <= $maxkk; ++$kk) {
                                        // restore special characters
                                        $lnstring[1][$kk] = str_replace('#!#OP#!#', '(', $lnstring[1][$kk]);
                                        $lnstring[1][$kk] = str_replace('#!#CP#!#', ')', $lnstring[1][$kk]);
                                        // store number of spaces on the strings
                                        $lnstring[2][$kk] = substr_count($lnstring[1][$kk], $spacestr);
                                        // count total spaces on line
                                        $ns += $lnstring[2][$kk];
                                        $lnstring[3][$kk] = $ns;
                                    }
                                    if ($ns == 0) {
                                        $ns = 1;
                                    }
                                    // calculate additional space to add to each existing space
                                    $spacewidth = ($mdiff / ($ns - $no)) * $this->k;
                                    $spacewidthu = -1000 * ($mdiff + (($ns + $no) * $one_space_width)) / $ns / $this->FontSize;
                                    $nsmax = $ns;
                                    $ns = 0;
                                    reset($lnstring);
                                    $offset = 0;
                                    $strcount = 0;
                                    $prev_epsposbeg = 0;
                                    $textpos = 0;
                                    if ($this->isRTLTextDir()) {
                                        $textpos = $this->wPt;
                                    }
                                    global $spacew;
                                    while (preg_match('/([0-9\.\+\-]*)[\s](Td|cm|m|l|c|re)[\s]/x', $pmid, $strpiece, PREG_OFFSET_CAPTURE, $offset) == 1) {
                                        // check if we are inside a string section '[( ... )]'
                                        $stroffset = strpos($pmid, '[(', $offset);
                                        if (($stroffset !== false) AND ($stroffset <= $strpiece[2][1])) {
                                            // set offset to the end of string section
                                            $offset = strpos($pmid, ')]', $stroffset);
                                            while (($offset !== false) AND ($pmid{($offset - 1)} == '\\')) {
                                                $offset = strpos($pmid, ')]', ($offset + 1));
                                            }
                                            if ($offset === false) {
                                                $this->Error('HTML Justification: malformed PDF code.');
                                            }
                                            continue;
                                        }
                                        if ($this->isRTLTextDir()) {
                                            $spacew = ($spacewidth * ($nsmax - $ns));
                                        } else {
                                            $spacew = ($spacewidth * $ns);
                                        }
                                        $offset = $strpiece[2][1] + strlen($strpiece[2][0]);
                                        $epsposbeg = strpos($pmid, 'q'.$this->epsmarker, $offset);
                                        $epsposend = strpos($pmid, $this->epsmarker.'Q', $offset) + strlen($this->epsmarker.'Q');
                                        if ((($epsposbeg > 0) AND ($epsposend > 0) AND ($offset > $epsposbeg) AND ($offset < $epsposend))
                                            OR (($epsposbeg === false) AND ($epsposend > 0) AND ($offset < $epsposend))) {
                                            // shift EPS images
                                            $trx = sprintf('1 0 0 1 %.3F 0 cm', $spacew);
                                            $epsposbeg = strpos($pmid, 'q'.$this->epsmarker, ($prev_epsposbeg - 6));
                                            $pmid_b = substr($pmid, 0, $epsposbeg);
                                            $pmid_m = substr($pmid, $epsposbeg, ($epsposend - $epsposbeg));
                                            $pmid_e = substr($pmid, $epsposend);
                                            $pmid = $pmid_b."\nq\n".$trx."\n".$pmid_m."\nQ\n".$pmid_e;
                                            $offset = $epsposend;
                                            continue;

                                        }
                                        $prev_epsposbeg = $epsposbeg;
                                        $currentxpos = 0;
                                        // shift blocks of code
                                        switch ($strpiece[2][0]) {
                                            case 'Td':
                                            case 'cm':
                                            case 'm':
                                            case 'l': {
                                                // get current X position
                                                preg_match('/([0-9\.\+\-]*)[\s]('.$strpiece[1][0].')[\s]('.$strpiece[2][0].')([\s]*)/x', $pmid, $xmatches);
                                                $currentxpos = $xmatches[1];
                                                $textpos = $currentxpos;
                                                if (($strcount <= $maxkk) AND ($strpiece[2][0] == 'Td')) {
                                                    $ns = $lnstring[3][$strcount];
                                                    if ($this->isRTLTextDir()) {
                                                        $spacew = ($spacewidth * ($nsmax - $ns));
                                                    }
                                                    ++$strcount;
                                                }
                                                // justify block
                                                $pmid = preg_replace_callback('/([0-9\.\+\-]*)[\s]('.$strpiece[1][0].')[\s]('.$strpiece[2][0].')([\s]*)/x',
                                                    create_function('$matches', 'global $spacew;
                                                    $newx = sprintf("%.2F",(floatval($matches[1]) + $spacew));
                                                    return "".$newx." ".$matches[2]." x*#!#*x".$matches[3].$matches[4];'), $pmid, 1);
                                                break;
                                            }
                                            case 're': {
                                                // justify block
                                                if (!$this->empty_string($this->lispacer)) {
                                                    $this->lispacer = '';
                                                    continue;
                                                }
                                                preg_match('/([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]('.$strpiece[1][0].')[\s](re)([\s]*)/x', $pmid, $xmatches);
                                                $currentxpos = $xmatches[1];
                                                global $x_diff, $w_diff;
                                                $x_diff = 0;
                                                $w_diff = 0;
                                                if ($this->isRTLTextDir()) { // RTL
                                                    if ($currentxpos < $textpos) {
                                                        $x_diff = ($spacewidth * ($nsmax - $lnstring[3][$strcount]));
                                                        $w_diff = ($spacewidth * $lnstring[2][$strcount]);
                                                    } else {
                                                        if ($strcount > 0) {
                                                            $x_diff = ($spacewidth * ($nsmax - $lnstring[3][($strcount - 1)]));
                                                            $w_diff = ($spacewidth * $lnstring[2][($strcount - 1)]);
                                                        }
                                                    }
                                                } else { // LTR
                                                    if ($currentxpos > $textpos) {
                                                        if ($strcount > 0) {
                                                            $x_diff = ($spacewidth * $lnstring[3][($strcount - 1)]);
                                                        }
                                                        $w_diff = ($spacewidth * $lnstring[2][$strcount]);
                                                    } else {
                                                        if ($strcount > 1) {
                                                            $x_diff = ($spacewidth * $lnstring[3][($strcount - 2)]);
                                                        }
                                                        if ($strcount > 0) {
                                                            $w_diff = ($spacewidth * $lnstring[2][($strcount - 1)]);
                                                        }
                                                    }
                                                }
                                                $pmid = preg_replace_callback('/('.$xmatches[1].')[\s]('.$xmatches[2].')[\s]('.$xmatches[3].')[\s]('.$strpiece[1][0].')[\s](re)([\s]*)/x',
                                                    create_function('$matches', 'global $x_diff, $w_diff;
                                                    $newx = sprintf("%.2F",(floatval($matches[1]) + $x_diff));
                                                    $neww = sprintf("%.2F",(floatval($matches[3]) + $w_diff));
                                                    return "".$newx." ".$matches[2]." ".$neww." ".$matches[4]." x*#!#*x".$matches[5].$matches[6];'), $pmid, 1);
                                                break;
                                            }
                                            case 'c': {
                                                // get current X position
                                                preg_match('/([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]('.$strpiece[1][0].')[\s](c)([\s]*)/x', $pmid, $xmatches);
                                                $currentxpos = $xmatches[1];
                                                // justify block
                                                $pmid = preg_replace_callback('/('.$xmatches[1].')[\s]('.$xmatches[2].')[\s]('.$xmatches[3].')[\s]('.$xmatches[4].')[\s]('.$xmatches[5].')[\s]('.$strpiece[1][0].')[\s](c)([\s]*)/x',
                                                    create_function('$matches', 'global $spacew;
                                                    $newx1 = sprintf("%.3F",(floatval($matches[1]) + $spacew));
                                                    $newx2 = sprintf("%.3F",(floatval($matches[3]) + $spacew));
                                                    $newx3 = sprintf("%.3F",(floatval($matches[5]) + $spacew));
                                                    return "".$newx1." ".$matches[2]." ".$newx2." ".$matches[4]." ".$newx3." ".$matches[6]." x*#!#*x".$matches[7].$matches[8];'), $pmid, 1);
                                                break;
                                            }
                                        }
                                        // shift the annotations and links
                                        if (isset($this->PageAnnots[$this->page])) {
                                            $cxpos = ($currentxpos / $this->k);
                                            $lmpos = ($this->lMargin + $this->cMargin + $this->feps);
                                            foreach ($this->PageAnnots[$this->page] as $pak => $pac) {
                                                if (($pac['y'] >= $minstartliney) AND (($pac['x'] * $this->k) >= ($currentxpos - $this->feps)) AND (($pac['x'] * $this->k) <= ($currentxpos + $this->feps))) {
                                                    if ($cxpos > $lmpos) {
                                                        $this->PageAnnots[$this->page][$pak]['x'] += ($spacew / $this->k);
                                                        $this->PageAnnots[$this->page][$pak]['w'] += (($spacewidth * $pac['numspaces']) / $this->k);
                                                    } else {
                                                        $this->PageAnnots[$this->page][$pak]['w'] += (($spacewidth * $pac['numspaces']) / $this->k);
                                                    }
                                                    break;
                                                }
                                            }
                                        }
                                    } // end of while
                                    // remove markers
                                    $pmid = str_replace('x*#!#*x', '', $pmid);
                                    if ($this->isUnicodeFont()) {
                                        // multibyte characters
                                        $spacew = $spacewidthu;
                                        $pmidtemp = $pmid;
                                        // escape special characters
                                        $pmidtemp = preg_replace('/[\\\][\(]/x', '\\#!#OP#!#', $pmidtemp);
                                        $pmidtemp = preg_replace('/[\\\][\)]/x', '\\#!#CP#!#', $pmidtemp);
                                        $pmid = preg_replace_callback("/\[\(([^\)]*)\)\]/x",
                                                    create_function('$matches', 'global $spacew;
                                                    $matches[1] = str_replace("#!#OP#!#", "(", $matches[1]);
                                                    $matches[1] = str_replace("#!#CP#!#", ")", $matches[1]);
                                                    return "[(".str_replace(chr(0).chr(32), ") ".sprintf("%.3F", $spacew)." (", $matches[1]).")]";'), $pmidtemp);
                                        $this->setPageBuffer($startlinepage, $pstart."\n".$pmid."\n".$pend);
                                        $endlinepos = strlen($pstart."\n".$pmid."\n");
                                    } else {
                                        // non-unicode (single-byte characters)
                                        $rs = sprintf('%.3F Tw', $spacewidth);
                                        $pmid = preg_replace("/\[\(/x", $rs.' [(', $pmid);
                                        $this->setPageBuffer($startlinepage, $pstart."\n".$pmid."\nBT 0 Tw ET\n".$pend);
                                        $endlinepos = strlen($pstart."\n".$pmid."\nBT 0 Tw ET\n");
                                    }
                                }
                            } // end of J
                        } // end if $startlinex
                        if (($t_x != 0) OR ($yshift < 0)) {
                            // shift the line
                            $trx = sprintf('1 0 0 1 %.3F %.3F cm', ($t_x * $this->k), ($yshift * $this->k));
                            $this->setPageBuffer($startlinepage, $pstart."\nq\n".$trx."\n".$pmid."\nQ\n".$pend);
                            $endlinepos = strlen($pstart."\nq\n".$trx."\n".$pmid."\nQ\n");
                            // shift the annotations and links
                            if (isset($this->PageAnnots[$this->page])) {
                                foreach ($this->PageAnnots[$this->page] as $pak => $pac) {
                                    if ($pak >= $pask) {
                                        $this->PageAnnots[$this->page][$pak]['x'] += $t_x;
                                        $this->PageAnnots[$this->page][$pak]['y'] -= $yshift;
                                    }
                                }
                            }
                            $this->y -= $yshift;
                        }
                    }
                    $pbrk = $this->checkPageBreak($this->lasth);
                    $this->newline = false;
                    $startlinex = $this->x;
                    $startliney = $this->y;
                    if ($dom[$dom[$key]['parent']]['value'] == 'sup') {
                        $startliney -= ((0.3 * $this->FontSizePt) / $this->k);
                    } elseif ($dom[$dom[$key]['parent']]['value'] == 'sub') {
                        $startliney -= (($this->FontSizePt / 0.7) / $this->k);
                    } else {
                        $minstartliney = $startliney;
                        $maxbottomliney = ($this->y + (($fontsize * $this->cell_height_ratio) / $this->k));
                    }
                    $startlinepage = $this->page;
                    if (isset($endlinepos) AND (!$pbrk)) {
                        $startlinepos = $endlinepos;
                    } else {
                        if (!$this->InFooter) {
                            if (isset($this->footerlen[$this->page])) {
                                $this->footerpos[$this->page] = $this->pagelen[$this->page] - $this->footerlen[$this->page];
                            } else {
                                $this->footerpos[$this->page] = $this->pagelen[$this->page];
                            }
                            $startlinepos = $this->footerpos[$this->page];
                        } else {
                            $startlinepos = $this->pagelen[$this->page];
                        }
                    }
                    unset($endlinepos);
                    $plalign = $lalign;
                    if (isset($this->PageAnnots[$this->page])) {
                        $pask = count($this->PageAnnots[$this->page]);
                    } else {
                        $pask = 0;
                    }
                    if (!($dom[$key]['tag'] AND !$dom[$key]['opening'] AND ($dom[$key]['value'] == 'table') AND ($this->emptypagemrk[$this->page] == $this->pagelen[$this->page]))) {
                        $this->SetFont($fontname, $fontstyle, $fontsize);
                        if ($wfill) {
                            $this->SetFillColorArray($this->bgcolor);
                        }
                    }
                } // end newline
                if (isset($opentagpos)) {
                    unset($opentagpos);
                }
                if ($dom[$key]['tag']) {
                    if ($dom[$key]['opening']) {
                        // get text indentation (if any)
                        if (isset($dom[$key]['text-indent']) AND $dom[$key]['block']) {
                            $this->textindent = $dom[$key]['text-indent'];
                            $this->newline = true;
                        }
                        // table
                        if ($dom[$key]['value'] == 'table') {
                            // available page width
                            if ($this->rtl) {
                                $wtmp = $this->x - $this->lMargin;
                            } else {
                                $wtmp = $this->w - $this->rMargin - $this->x;
                            }
                            if (isset($dom[$key]['attribute']['cellspacing'])) {
                                $cellspacing = $this->getHTMLUnitToUnits($dom[$key]['attribute']['cellspacing'], 1, 'px');
                            } else {
                                $cellspacing = 0;
                            }
                            // table width
                            if (isset($dom[$key]['width'])) {
                                $table_width = $this->getHTMLUnitToUnits($dom[$key]['width'], $wtmp, 'px');
                            } else {
                                $table_width = $wtmp;
                            }
                            $table_width -= (2 * $cellspacing);
                            if (!$this->inthead) {
                                $this->y += $cellspacing;
                            }
                            if ($this->rtl) {
                                $cellspacingx = -$cellspacing;
                            } else {
                                $cellspacingx = $cellspacing;
                            }
                            // total table width without cellspaces
                            $table_columns_width = ($table_width - ($cellspacing * ($dom[$key]['cols'] - 1)));
                            // minimum column width
                            $table_min_column_width = ($table_columns_width / $dom[$key]['cols']);
                            // array of custom column widths
                            $table_colwidths = array_fill(0, $dom[$key]['cols'], $table_min_column_width);
                        }
                        // table row
                        if ($dom[$key]['value'] == 'tr') {
                            // reset column counter
                            $colid = 0;
                        }
                        // table cell
                        if (($dom[$key]['value'] == 'td') OR ($dom[$key]['value'] == 'th')) {
                            $trid = $dom[$key]['parent'];
                            $table_el = $dom[$trid]['parent'];
                            if (!isset($dom[$table_el]['cols'])) {
                                $dom[$table_el]['cols'] = $dom[$trid]['cols'];
                            }
                            // store border info
                            $tdborder = 0;
                            if (isset($dom[$key]['border']) AND !empty($dom[$key]['border'])) {
                                $tdborder = $dom[$key]['border'];
                            }
                            $colspan = $dom[$key]['attribute']['colspan'];
                            $oldmargin = $this->cMargin;
                            if (isset($dom[($dom[$trid]['parent'])]['attribute']['cellpadding'])) {
                                $currentcmargin = $this->getHTMLUnitToUnits($dom[($dom[$trid]['parent'])]['attribute']['cellpadding'], 1, 'px');
                            } else {
                                $currentcmargin = 0;
                            }
                            $this->cMargin = $currentcmargin;
                            if (isset($dom[$key]['height'])) {
                                // minimum cell height
                                $cellh = $this->getHTMLUnitToUnits($dom[$key]['height'], 0, 'px');
                            } else {
                                $cellh = 0;
                            }
                            if (isset($dom[$key]['content'])) {
                                $cell_content = $dom[$key]['content'];
                            } else {
                                $cell_content = '&nbsp;';
                            }
                            $tagtype = $dom[$key]['value'];
                            $parentid = $key;
                            while (($key < $maxel) AND (!(($dom[$key]['tag']) AND (!$dom[$key]['opening']) AND ($dom[$key]['value'] == $tagtype) AND ($dom[$key]['parent'] == $parentid)))) {
                                // move $key index forward
                                ++$key;
                            }
                            if (!isset($dom[$trid]['startpage'])) {
                                $dom[$trid]['startpage'] = $this->page;
                            } else {
                                $this->setPage($dom[$trid]['startpage']);
                            }
                            if (!isset($dom[$trid]['startcolumn'])) {
                                $dom[$trid]['startcolumn'] = $this->current_column;
                            } elseif ($this->current_column != $dom[$trid]['startcolumn']) {
                                $tmpx = $this->x;
                                $this->selectColumn($dom[$trid]['startcolumn']);
                                $this->x = $tmpx;
                            }
                            if (!isset($dom[$trid]['starty'])) {
                                $dom[$trid]['starty'] = $this->y;
                            } else {
                                $this->y = $dom[$trid]['starty'];
                            }
                            if (!isset($dom[$trid]['startx'])) {
                                $dom[$trid]['startx'] = $this->x;
                                $this->x += $cellspacingx;
                            } else {
                                $this->x += ($cellspacingx / 2);
                            }
                            if (isset($dom[$parentid]['attribute']['rowspan'])) {
                                $rowspan = intval($dom[$parentid]['attribute']['rowspan']);
                            } else {
                                $rowspan = 1;
                            }
                            // skip row-spanned cells started on the previous rows
                            if (isset($dom[$table_el]['rowspans'])) {
                                $rsk = 0;
                                $rskmax = count($dom[$table_el]['rowspans']);
                                while ($rsk < $rskmax) {
                                    $trwsp = $dom[$table_el]['rowspans'][$rsk];
                                    $rsstartx = $trwsp['startx'];
                                    $rsendx = $trwsp['endx'];
                                    // account for margin changes
                                    if ($trwsp['startpage'] < $this->page) {
                                        if (($this->rtl) AND ($this->pagedim[$this->page]['orm'] != $this->pagedim[$trwsp['startpage']]['orm'])) {
                                            $dl = ($this->pagedim[$this->page]['orm'] - $this->pagedim[$trwsp['startpage']]['orm']);
                                            $rsstartx -= $dl;
                                            $rsendx -= $dl;
                                        } elseif ((!$this->rtl) AND ($this->pagedim[$this->page]['olm'] != $this->pagedim[$trwsp['startpage']]['olm'])) {
                                            $dl = ($this->pagedim[$this->page]['olm'] - $this->pagedim[$trwsp['startpage']]['olm']);
                                            $rsstartx += $dl;
                                            $rsendx += $dl;
                                        }
                                    }
                                    if (($trwsp['rowspan'] > 0)
                                        AND ($rsstartx > ($this->x - $cellspacing - $currentcmargin - $this->feps))
                                        AND ($rsstartx < ($this->x + $cellspacing + $currentcmargin + $this->feps))
                                        AND (($trwsp['starty'] < ($this->y - $this->feps)) OR ($trwsp['startpage'] < $this->page) OR ($trwsp['startcolumn'] < $this->current_column))) {
                                        // set the starting X position of the current cell
                                        $this->x = $rsendx + $cellspacingx;
                                        // increment column indicator
                                        $colid += $trwsp['colspan'];
                                        if (($trwsp['rowspan'] == 1)
                                            AND (isset($dom[$trid]['endy']))
                                            AND (isset($dom[$trid]['endpage']))
                                            AND (isset($dom[$trid]['endcolumn']))
                                            AND ($trwsp['endpage'] == $dom[$trid]['endpage'])
                                            AND ($trwsp['endcolumn'] == $dom[$trid]['endcolumn'])) {
                                            // set ending Y position for row
                                            $dom[$table_el]['rowspans'][$rsk]['endy'] = max($dom[$trid]['endy'], $trwsp['endy']);
                                            $dom[$trid]['endy'] = $dom[$table_el]['rowspans'][$rsk]['endy'];
                                        }
                                        $rsk = 0;
                                    } else {
                                        ++$rsk;
                                    }
                                }
                            }
                            if (isset($dom[$parentid]['width'])) {
                                // user specified width
                                $cellw = $this->getHTMLUnitToUnits($dom[$parentid]['width'], $table_columns_width, 'px');
                                $tmpcw = ($cellw / $colspan);
                                for ($i = 0; $i < $colspan; ++$i) {
                                    $table_colwidths[($colid + $i)] = $tmpcw;
                                }
                            } else {
                                // inherit column width
                                $cellw = 0;
                                for ($i = 0; $i < $colspan; ++$i) {
                                    $cellw += $table_colwidths[($colid + $i)];
                                }
                            }
                            $cellw += (($colspan - 1) * $cellspacing);
                            // increment column indicator
                            $colid += $colspan;
                            // add rowspan information to table element
                            if ($rowspan > 1) {
                                $trsid = array_push($dom[$table_el]['rowspans'], array('trid' => $trid, 'rowspan' => $rowspan, 'mrowspan' => $rowspan, 'colspan' => $colspan, 'startpage' => $this->page, 'startcolumn' => $this->current_column, 'startx' => $this->x, 'starty' => $this->y));
                            }
                            $cellid = array_push($dom[$trid]['cellpos'], array('startx' => $this->x));
                            if ($rowspan > 1) {
                                $dom[$trid]['cellpos'][($cellid - 1)]['rowspanid'] = ($trsid - 1);
                            }
                            // push background colors
                            if (isset($dom[$parentid]['bgcolor']) AND ($dom[$parentid]['bgcolor'] !== false)) {
                                $dom[$trid]['cellpos'][($cellid - 1)]['bgcolor'] = $dom[$parentid]['bgcolor'];
                            }
                            // store border info
                            if (isset($tdborder) AND !empty($tdborder)) {
                                $dom[$trid]['cellpos'][($cellid - 1)]['border'] = $tdborder;
                            }
                            $prevLastH = $this->lasth;
                            // store some info for multicolumn mode
                            if ($this->rtl) {
                                $this->colxshift['x'] = $this->w - $this->x - $this->rMargin;
                            } else {
                                $this->colxshift['x'] = $this->x - $this->lMargin;
                            }
                            $this->colxshift['s'] = $cellspacing;
                            $this->colxshift['p'] = $currentcmargin;
                            // ****** write the cell content ******
                            $this->MultiCell($cellw, $cellh, $cell_content, false, $lalign, false, 2, '', '', true, 0, true);
                            // restore some values
                            $this->colxshift = array('x' => 0, 's' => 0, 'p' => 0);
                            $this->lasth = $prevLastH;
                            $this->cMargin = $oldmargin;
                            $dom[$trid]['cellpos'][($cellid - 1)]['endx'] = $this->x;
                            // update the end of row position
                            if ($rowspan <= 1) {
                                if (isset($dom[$trid]['endy'])) {
                                    if (($this->page == $dom[$trid]['endpage']) AND ($this->current_column == $dom[$trid]['endcolumn'])) {
                                        $dom[$trid]['endy'] = max($this->y, $dom[$trid]['endy']);
                                    } elseif (($this->page > $dom[$trid]['endpage']) OR ($this->current_column > $dom[$trid]['endcolumn'])) {
                                        $dom[$trid]['endy'] = $this->y;
                                    }
                                } else {
                                    $dom[$trid]['endy'] = $this->y;
                                }
                                if (isset($dom[$trid]['endpage'])) {
                                    $dom[$trid]['endpage'] = max($this->page, $dom[$trid]['endpage']);
                                } else {
                                    $dom[$trid]['endpage'] = $this->page;
                                }
                                if (isset($dom[$trid]['endcolumn'])) {
                                    $dom[$trid]['endcolumn'] = max($this->current_column, $dom[$trid]['endcolumn']);
                                } else {
                                    $dom[$trid]['endcolumn'] = $this->current_column;
                                }
                            } else {
                                // account for row-spanned cells
                                $dom[$table_el]['rowspans'][($trsid - 1)]['endx'] = $this->x;
                                $dom[$table_el]['rowspans'][($trsid - 1)]['endy'] = $this->y;
                                $dom[$table_el]['rowspans'][($trsid - 1)]['endpage'] = $this->page;
                                $dom[$table_el]['rowspans'][($trsid - 1)]['endcolumn'] = $this->current_column;
                            }
                            if (isset($dom[$table_el]['rowspans'])) {
                                // update endy and endpage on rowspanned cells
                                foreach ($dom[$table_el]['rowspans'] as $k => $trwsp) {
                                    if ($trwsp['rowspan'] > 0) {
                                        if (isset($dom[$trid]['endpage'])) {
                                            if (($trwsp['endpage'] == $dom[$trid]['endpage']) AND ($trwsp['endcolumn'] == $dom[$trid]['endcolumn'])) {
                                                $dom[$table_el]['rowspans'][$k]['endy'] = max($dom[$trid]['endy'], $trwsp['endy']);
                                            } elseif (($trwsp['endpage'] < $dom[$trid]['endpage']) OR ($trwsp['endcolumn'] < $dom[$trid]['endcolumn'])) {
                                                $dom[$table_el]['rowspans'][$k]['endy'] = $dom[$trid]['endy'];
                                                $dom[$table_el]['rowspans'][$k]['endpage'] = $dom[$trid]['endpage'];
                                                $dom[$table_el]['rowspans'][$k]['endcolumn'] = $dom[$trid]['endcolumn'];
                                            } else {
                                                $dom[$trid]['endy'] = $this->pagedim[$dom[$trid]['endpage']]['hk'] - $this->pagedim[$dom[$trid]['endpage']]['bm'];
                                            }
                                        }
                                    }
                                }
                            }
                            $this->x += ($cellspacingx / 2);
                        } else {
                            // opening tag (or self-closing tag)
                            if (!isset($opentagpos)) {
                                if (!$this->InFooter) {
                                    if (isset($this->footerlen[$this->page])) {
                                        $this->footerpos[$this->page] = $this->pagelen[$this->page] - $this->footerlen[$this->page];
                                    } else {
                                        $this->footerpos[$this->page] = $this->pagelen[$this->page];
                                    }
                                    $opentagpos = $this->footerpos[$this->page];
                                }
                            }
                            $this->openHTMLTagHandler($dom, $key, $cell);
                        }
                    } else { // closing tag
                        $prev_numpages = $this->numpages;
                        $old_bordermrk = $this->bordermrk[$this->page];
                        $this->closeHTMLTagHandler($dom, $key, $cell, $maxbottomliney);
                        if ($this->bordermrk[$this->page] > $old_bordermrk) {
                            $startlinepos += ($this->bordermrk[$this->page] - $old_bordermrk);
                        }
                        if ($prev_numpages > $this->numpages) {
                            $startlinepage = $this->page;
                        }
                    }
                } elseif (strlen($dom[$key]['value']) > 0) {
                    // print list-item
                    if (!$this->empty_string($this->lispacer) AND ($this->lispacer != '^')) {
                        $this->SetFont($pfontname, $pfontstyle, $pfontsize);
                        $this->lasth = $this->FontSize * $this->cell_height_ratio;
                        $minstartliney = $this->y;
                        $maxbottomliney = ($startliney + ($this->FontSize * $this->cell_height_ratio));
                        $this->putHtmlListBullet($this->listnum, $this->lispacer, $pfontsize);
                        $this->SetFont($curfontname, $curfontstyle, $curfontsize);
                        $this->lasth = $this->FontSize * $this->cell_height_ratio;
                        if (is_numeric($pfontsize) AND ($pfontsize > 0) AND is_numeric($curfontsize) AND ($curfontsize > 0) AND ($pfontsize != $curfontsize)) {
                            $pfontascent = $this->getFontAscent($pfontname, $pfontstyle, $pfontsize);
                            $pfontdescent = $this->getFontDescent($pfontname, $pfontstyle, $pfontsize);
                            $this->y += ((($pfontsize - $curfontsize) * $this->cell_height_ratio / $this->k) + $pfontascent - $curfontascent - $pfontdescent + $curfontdescent) / 2;
                            $minstartliney = min($this->y, $minstartliney);
                            $maxbottomliney = max(($this->y + (($pfontsize * $this->cell_height_ratio) / $this->k)), $maxbottomliney);
                        }
                    }
                    // text
                    $this->htmlvspace = 0;
                    if ((!$this->premode) AND $this->isRTLTextDir()) {
                        // reverse spaces order
                        $lsp = ''; // left spaces
                        $rsp = ''; // right spaces
                        if (preg_match('/^('.$this->re_space['p'].'+)/'.$this->re_space['m'], $dom[$key]['value'], $matches)) {
                            $lsp = $matches[1];
                        }
                        if (preg_match('/('.$this->re_space['p'].'+)$/'.$this->re_space['m'], $dom[$key]['value'], $matches)) {
                            $rsp = $matches[1];
                        }
                        $dom[$key]['value'] = $rsp.$this->stringTrim($dom[$key]['value']).$lsp;
                    }
                    if ($newline) {
                        if (!$this->premode) {
                            $prelen = strlen($dom[$key]['value']);
                            if ($this->isRTLTextDir()) {
                                // right trim except non-breaking space
                                $dom[$key]['value'] = $this->stringRightTrim($dom[$key]['value']);
                            } else {
                                // left trim except non-breaking space
                                $dom[$key]['value'] = $this->stringLeftTrim($dom[$key]['value']);
                            }
                            $postlen = strlen($dom[$key]['value']);
                            if (($postlen == 0) AND ($prelen > 0)) {
                                $dom[$key]['trimmed_space'] = true;
                            }
                        }
                        $newline = false;
                        $firstblock = true;
                    } else {
                        $firstblock = false;
                        // replace empty multiple spaces string with a single space
                        $dom[$key]['value'] = preg_replace('/^'.$this->re_space['p'].'+$/'.$this->re_space['m'], chr(32), $dom[$key]['value']);
                    }
                    $strrest = '';
                    if ($this->rtl) {
                        $this->x -= $this->textindent;
                    } else {
                        $this->x += $this->textindent;
                    }
                    if (!isset($dom[$key]['trimmed_space']) OR !$dom[$key]['trimmed_space']) {
                        if (!empty($this->HREF) AND (isset($this->HREF['url']))) {
                            // HTML <a> Link
                            $hrefcolor = '';
                            if (isset($dom[($dom[$key]['parent'])]['fgcolor']) AND ($dom[($dom[$key]['parent'])]['fgcolor'] !== false)) {
                                $hrefcolor = $dom[($dom[$key]['parent'])]['fgcolor'];
                            }
                            $hrefstyle = -1;
                            if (isset($dom[($dom[$key]['parent'])]['fontstyle']) AND ($dom[($dom[$key]['parent'])]['fontstyle'] !== false)) {
                                $hrefstyle = $dom[($dom[$key]['parent'])]['fontstyle'];
                            }
                            $strrest = $this->addHtmlLink($this->HREF['url'], $dom[$key]['value'], $wfill, true, $hrefcolor, $hrefstyle, true);
                        } else {
                            // check the next text block for continuity
                            $wadj = 0;
                            $nkey = ($key + 1);
                            while (isset($dom[$nkey]) AND $dom[$nkey]['tag'] AND (!$dom[$nkey]['block'])) {
                                ++$nkey;
                            }
                            if (isset($dom[$nkey]) AND (!$dom[$nkey]['block'])) {
                                $nextstr = preg_split('/'.$this->re_space['p'].'+/'.$this->re_space['m'], $dom[$nkey]['value']);
                                $nextstr = $nextstr[0];
                                if (!$this->empty_string($nextstr)) {
                                    // preserve line continuity
                                    $wadj = $this->GetStringWidth($nextstr);
                                }
                            }
                            // ****** write only until the end of the line and get the rest ******
                            $strrest = $this->Write($this->lasth, $dom[$key]['value'], '', $wfill, '', false, 0, true, $firstblock, 0, $wadj);
                        }
                    }
                    $this->textindent = 0;
                    if (strlen($strrest) > 0) {
                        // store the remaining string on the previous $key position
                        $this->newline = true;
                        if ($strrest == $dom[$key]['value']) {
                            // used to avoid infinite loop
                            ++$loop;
                        } else {
                            $loop = 0;
                        }
                        $dom[$key]['value'] = $strrest;
                        if ($cell) {
                            if ($this->rtl) {
                                $this->x -= $this->cMargin;
                            } else {
                                $this->x += $this->cMargin;
                            }
                        }
                        if ($loop < 3) {
                            --$key;
                        }
                    } else {
                        $loop = 0;
                    }
                }
                ++$key;
                if (isset($dom[$key]['tag']) AND $dom[$key]['tag'] AND (!isset($dom[$key]['opening']) OR !$dom[$key]['opening']) AND isset($dom[($dom[$key]['parent'])]['attribute']['nobr']) AND ($dom[($dom[$key]['parent'])]['attribute']['nobr'] == 'true')) {
                    if ( (!$undo) AND (($this->start_transaction_page == ($this->numpages - 1)) OR ($this->y < $this->start_transaction_y))) {
                        // restore previous object
                        $this->rollbackTransaction(true);
                        // restore previous values
                        foreach ($this_method_vars as $vkey => $vval) {
                            $$vkey = $vval;
                        }
                        // add a page (or trig AcceptPageBreak() for multicolumn mode)
                        $pre_y = $this->y;
                        if ((!$this->checkPageBreak($this->PageBreakTrigger + 1)) AND ($this->y < $pre_y)) {
                            $startliney = $this->y;
                        }
                        $undo = true; // avoid infinite loop
                    } else {
                        $undo = false;
                    }
                }
            } // end for each $key
            // align the last line
            if (isset($startlinex)) {
                $yshift = $minstartliney - $startliney;
                if (($yshift > 0) OR ($this->page > $startlinepage)) {
                    $yshift = 0;
                }
                $t_x = 0;
                // the last line must be shifted to be aligned as requested
                $linew = abs($this->endlinex - $startlinex);
                $pstart = substr($this->getPageBuffer($startlinepage), 0, $startlinepos);
                if (isset($opentagpos) AND isset($this->footerlen[$startlinepage]) AND (!$this->InFooter)) {
                    $this->footerpos[$startlinepage] = $this->pagelen[$startlinepage] - $this->footerlen[$startlinepage];
                    $midpos = min($opentagpos, $this->footerpos[$startlinepage]);
                } elseif (isset($opentagpos)) {
                    $midpos = $opentagpos;
                } elseif (isset($this->footerlen[$startlinepage]) AND (!$this->InFooter)) {
                    $this->footerpos[$startlinepage] = $this->pagelen[$startlinepage] - $this->footerlen[$startlinepage];
                    $midpos = $this->footerpos[$startlinepage];
                } else {
                    $midpos = 0;
                }
                if ($midpos > 0) {
                    $pmid = substr($this->getPageBuffer($startlinepage), $startlinepos, ($midpos - $startlinepos));
                    $pend = substr($this->getPageBuffer($startlinepage), $midpos);
                } else {
                    $pmid = substr($this->getPageBuffer($startlinepage), $startlinepos);
                    $pend = '';
                }
                if ((isset($plalign) AND ((($plalign == 'C') OR (($plalign == 'R') AND (!$this->rtl)) OR (($plalign == 'L') AND ($this->rtl)))))) {
                    // calculate shifting amount
                    $tw = $w;
                    if ($this->lMargin != $prevlMargin) {
                        $tw += ($prevlMargin - $this->lMargin);
                    }
                    if ($this->rMargin != $prevrMargin) {
                        $tw += ($prevrMargin - $this->rMargin);
                    }
                    $one_space_width = $this->GetStringWidth(chr(32));
                    $no = 0; // number of spaces on a line contained on a single block
                    if ($this->isRTLTextDir()) { // RTL
                        // remove left space if exist
                        $pos1 = $this->revstrpos($pmid, '[(');
                        if ($pos1 > 0) {
                            $pos1 = intval($pos1);
                            if ($this->isUnicodeFont()) {
                                $pos2 = intval($this->revstrpos($pmid, '[('.chr(0).chr(32)));
                                $spacelen = 2;
                            } else {
                                $pos2 = intval($this->revstrpos($pmid, '[('.chr(32)));
                                $spacelen = 1;
                            }
                            if ($pos1 == $pos2) {
                                $pmid = substr($pmid, 0, ($pos1 + 2)).substr($pmid, ($pos1 + 2 + $spacelen));
                                if (substr($pmid, $pos1, 4) == '[()]') {
                                    $linew -= $one_space_width;
                                } elseif ($pos1 == strpos($pmid, '[(')) {
                                    $no = 1;
                                }
                            }
                        }
                    } else { // LTR
                        // remove right space if exist
                        $pos1 = $this->revstrpos($pmid, ')]');
                        if ($pos1 > 0) {
                            $pos1 = intval($pos1);
                            if ($this->isUnicodeFont()) {
                                $pos2 = intval($this->revstrpos($pmid, chr(0).chr(32).')]')) + 2;
                                $spacelen = 2;
                            } else {
                                $pos2 = intval($this->revstrpos($pmid, chr(32).')]')) + 1;
                                $spacelen = 1;
                            }
                            if ($pos1 == $pos2) {
                                $pmid = substr($pmid, 0, ($pos1 - $spacelen)).substr($pmid, $pos1);
                                $linew -= $one_space_width;
                            }
                        }
                    }
                    $mdiff = ($tw - $linew);
                    if ($plalign == 'C') {
                        if ($this->rtl) {
                            $t_x = -($mdiff / 2);
                        } else {
                            $t_x = ($mdiff / 2);
                        }
                    } elseif ($plalign == 'R') {
                        // right alignment on LTR document
                        $t_x = $mdiff;
                    } elseif ($plalign == 'L') {
                        // left alignment on RTL document
                        $t_x = -$mdiff;
                    }
                } // end if startlinex
                if (($t_x != 0) OR ($yshift < 0)) {
                    // shift the line
                    $trx = sprintf('1 0 0 1 %.3F %.3F cm', ($t_x * $this->k), ($yshift * $this->k));
                    $this->setPageBuffer($startlinepage, $pstart."\nq\n".$trx."\n".$pmid."\nQ\n".$pend);
                    $endlinepos = strlen($pstart."\nq\n".$trx."\n".$pmid."\nQ\n");
                    // shift the annotations and links
                    if (isset($this->PageAnnots[$this->page])) {
                        foreach ($this->PageAnnots[$this->page] as $pak => $pac) {
                            if ($pak >= $pask) {
                                $this->PageAnnots[$this->page][$pak]['x'] += $t_x;
                                $this->PageAnnots[$this->page][$pak]['y'] -= $yshift;
                            }
                        }
                    }
                    $this->y -= $yshift;
                }
            }
            // restore previous values
            $this->setGraphicVars($gvars);
            if ($this->num_columns > 1) {
                $this->selectColumn();
            } elseif ($this->page > $prevPage) {
                $this->lMargin = $this->pagedim[$this->page]['olm'];
                $this->rMargin = $this->pagedim[$this->page]['orm'];
            }
            // restore previous list state
            $this->cell_height_ratio = $prev_cell_height_ratio;
            $this->listnum = $prev_listnum;
            $this->listordered = $prev_listordered;
            $this->listcount = $prev_listcount;
            $this->lispacer = $prev_lispacer;
            if ($ln AND (!($cell AND ($dom[$key-1]['value'] == 'table')))) {
                $this->Ln($this->lasth);
                if ($this->y < $maxbottomliney) {
                    $this->y = $maxbottomliney;
                }
            }
            unset($dom);
        }
	
	   
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
            
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
}

?>